(function ( exports ) {

    //region LocalizedLabelSet

    function LocalizedLabelSet () {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, LocalizedLabelSet, {
        'getMap': function () {
            return {
                'localizedLabels': 'localizedLabelCollection:LocalizedLabels',
                'userLocalizedLabel': 'localizedLabel:UserLocalizedLabel'
            };
        },
        getM: function () {
            return {
                localizedLabelCollection: [ 'LocalizedLabels' ],
                localizedLabel: [ 'UserLocalizedLabel' ]
            };
        }
    });

    //endregion LocalizedLabelSet

    //region OptionSetMetadataBase

    function OptionSetMetadataBase () {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, OptionSetMetadataBase, {
        getMap: function () {
            return (new COSA.ExtensibleObject((this.getBase()).getMap()))
                .extendWith(this.getBaseMapExtensions())
                .result();
        },
        getBaseMapExtensions: function () {
            return {
                'metadataId': 'string:MetadataId',
                'hasChanged': 'boolean:HasChanged',
                'description': 'localizedLabelSet:Description',
                'displayName': 'localizedLabelSet:DisplayName',
                'isCustomOptionSet':'boolean:IsCustomOptionSet',
                'isCustomizable':'managedProperty:IsCustomizable',
                'isGlobal':'boolean:IsGlobal',
                'isManaged':'boolean:IsManaged',
                'name':'string:Name',
                'optionSetType':'string:OptionSetType',
                'introducedVersion':'string:IntroducedVersion'
            };
        },
        getMExt: function () {
            return {
                localizedLabelSet: [ 'Description', 'DisplayName' ],
                boolean: [ 'HasChanged', 'IsGlobal', 'IsManaged', 'IsCustomOptionSet' ],
                string: [ 'MetadataId', 'Name', 'OptionSetType', 'IntroducedVersion' ],
                managedProperty: [ 'IsCustomizable' ]
            };
        }
    });

    //endregion OptionSetMetadataBase

    //region BoolOptionSetMetadata

    function BoolOptionSetMetadata () {
        OptionSetMetadataBase.call(this);
    }

    COSA.Util.deriveOverride(OptionSetMetadataBase, BoolOptionSetMetadata, {
        getBaseMapExtensions: function () {
            return {
                'falseOption':'optionMetadata:FalseOption',
                'trueOption':'optionMetadata:TrueOption'
            };
        }
    });

    //endregion BoolOptionSetMetadata

    //region OptionSetMetadata

    function OptionSetMetadata () {
        OptionSetMetadataBase.call(this);
    }

    COSA.Util.deriveOverride(OptionSetMetadataBase, OptionSetMetadata, {
        getBaseMapExtensions: function () {
            return {
                'options':'optionsCollection:Options'
            };
        }
    });

    //endregion OptionSetMetadata

    //region OptionMetadata

    function OptionMetadata () {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, OptionMetadata, {
        getMap: function () {
            return {
                'metadataId':'string:MetadataId',
                'hasChanged':'string:HasChanged',
                'description':'localizedLabelSet:Description',
                'isManaged':'boolean:IsManaged',
                'label':'localizedLabelSet:Label',
                'value':'int:Value'
            };
        }
    });

    //endregion OptionMetadata

    //region LocalizedLabel

    function LocalizedLabel () {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, LocalizedLabel, {
        getMap: function () {
            return {
                'metadataId': 'string:MetadataId',
                'hasChanged': 'string:HasChanged',
                'isManaged': 'boolean:IsManaged',
                'label': 'string:Label',
                'languageCode': 'int:LanguageCode'
            };
        }
    });

    //endregion LocalizedLabel

    //region ManagedProperty

    function ManagedProperty () {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, ManagedProperty, {
        getMap: function () {
            return {
                'canBeChanged': 'boolean:CanBeChanged',
                'managedPropertyLogicalName': 'string:ManagedPropertyLogicalName',
                'value': 'boolean:Value'
            };
        }
    });

    //endregion ManageProperty

    //region ValueNode

    function ValueNode ( ) {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, ValueNode, {
        deserialize: function ( node ) {
            var valueNode = node.node('Value');
            return typeof valueNode != 'undefined' ? node.node('Value').text() : null;
        }
    });

    //endregion ValueNode

    //region EntityMetadata

    function EntityMetadata () {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, EntityMetadata, {
        getMap: function () {
            return {
                'metadataId':'string:MetadataId',
                'hasChanged':'string:HasChanged',
                'activityTypeMask':'int:ActivityTypeMask',
                'attributes':'attributeMetadataCollection:Attributes',
                'autoCreateAccessTeams':'string:AutoCreateAccessTeams',
                'canBeInManyToMany':'managedProperty:CanBeInManyToMany',
                'canBePrimaryEntityInRelationship':'managedProperty:CanBePrimaryEntityInRelationship',
                'canBeRelatedEntityInRelationship':'managedProperty:CanBeRelatedEntityInRelationship',
                'canCreateAttributes':'managedProperty:CanCreateAttributes',
                'canCreateCharts':'managedProperty:CanCreateCharts',
                'canCreateForms':'managedProperty:CanCreateForms',
                'canCreateViews':'managedProperty:CanCreateViews',
                'canModifyAdditionalSettings':'managedProperty:CanModifyAdditionalSettings',
                'canTriggerWorkflow':'boolean:CanTriggerWorkflow',
                'description':'localizedLabelSet:Description',
                'displayCollectionName':'localizedLabelSet:DisplayCollectionName',
                'displayName':'localizedLabelSet:DisplayName',
                'enforceStateTransitions':'boolean:EnforceStateTransitions',
                'iconLargeName':'string:IconLargeName',
                'iconMediumName':'string:IconMediumName',
                'iconSmallName':'string:IconSmallName',
                'isAIRUpdated':'boolean:IsAIRUpdated',
                'isActivity':'boolean:IsActivity',
                'isActivityParty':'boolean:IsActivityParty',
                'isAuditEnabled':'managedProperty:IsAuditEnabled',
                'isAvailableOffline':'boolean:IsAvailableOffline',
                'isBusinessProcessEnabled':'boolean:IsBusinessProcessEnabled',
                'isChildEntity':'boolean:IsChildEntity',
                'isConnectionsEnabled':'managedProperty:IsConnectionsEnabled',
                'isCustomEntity':'boolean:IsCustomEntity',
                'isCustomizable':'managedProperty:IsCustomizable',
                'isDocumentManagementEnabled':'boolean:IsDocumentManagementEnabled',
                'isDuplicateDetectionEnabled':'managedProperty:IsDuplicateDetectionEnabled',
                'isEnabledForCharts':'boolean:IsEnabledForCharts',
                'isEnabledForTrace':'boolean:IsEnabledForTrace',
                'isImportable':'boolean:IsImportable',
                'isIntersect':'boolean:IsIntersect',
                'isMailMergeEnabled':'managedProperty:IsMailMergeEnabled',
                'isManaged':'boolean:IsManaged',
                'isMappable':'managedProperty:IsMappable',
                'isQuickCreateEnabled':'boolean:IsQuickCreateEnabled',
                'isReadOnlyInMobileClient':'managedProperty:IsReadOnlyInMobileClient',
                'isReadingPaneEnabled':'boolean:IsReadingPaneEnabled',
                'isRenameable':'managedProperty:IsRenameable',
                'isStateModelAware':'boolean:IsStateModelAware',
                'isValidForAdvancedFind':'boolean:IsValidForAdvancedFind',
                'isValidForQueue':'managedProperty:IsValidForQueue',
                'isVisibleInMobile':'managedProperty:IsVisibleInMobile',
                'isVisibleInMobileClient':'managedProperty:IsVisibleInMobileClient',
                'logicalName':'string:LogicalName',
                'manyToManyRelationships':'mMRelationshipCollection:ManyToManyRelationships',
                'manyToOneRelationships':'oMRelationshipCollection:ManyToOneRelationships',
                'objectTypeCode':'int:ObjectTypeCode',
                'oneToManyRelationships':'oMRelationshipCollection:OneToManyRelationships',
                'ownershipType':'string:OwnershipType',
                'primaryIdAttribute':'string:PrimaryIdAttribute',
                'primaryNameAttribute':'string:PrimaryNameAttribute',
                'privileges':'privilegesMetadataCollection:Privileges',
                'recurrenceBaseEntityLogicalName':'string:RecurrenceBaseEntityLogicalName',
                'reportViewName':'string:ReportViewName',
                'schemaName':'string:SchemaName',
                'introducedVersion':'string:IntroducedVersion',
                'primaryImageAttribute':'string:PrimaryImageAttribute',
                'canChangeHierarchicalRelationship':'managedProperty:CanChangeHierarchicalRelationship',
                'entityHelpUrl':'string:EntityHelpUrl',
                'entityHelpUrlEnabled':'boolean:EntityHelpUrlEnabled'
            };
        }
    });

    //endregion EntityMetadata

    //region SecurityPrivilegeMetadata

    function SecurityPrivilegeMetadata () {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, SecurityPrivilegeMetadata, {
        getMap: function () {
            return {
                'canBeBasic':'boolean:CanBeBasic',
                'canBeDeep':'boolean:CanBeDeep',
                'canBeGlobal':'boolean:CanBeGlobal',
                'canBeLocal':'boolean:CanBeLocal',
                'name':'string:Name',
                'privilegeId':'string:PrivilegeId',
                'privilegeType':'string:PrivilegeType'
            };
        }
    });

    //endregion SecurityPrivilegeMetadata

    //region ManyToManyRelationshipMetadata

    function ManyToManyRelationshipMetadata () {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, ManyToManyRelationshipMetadata, {
        getMap: function () {
            return {
                'metadataId':'string:MetadataId',
                'hasChanged':'string:HasChanged',
                'isCustomRelationship':'boolean:IsCustomRelationship',
                'isCustomizable':'managedProperty:IsCustomizable',
                'isManaged':'boolean:IsManaged',
                'isValidForAdvancedFind':'boolean:IsValidForAdvancedFind',
                'schemaName':'string:SchemaName',
                'securityTypes':'string:SecurityTypes',
                'introducedVersion':'string:IntroducedVersion',
                'relationshipType':'string:RelationshipType',
                'entity1AssociatedMenuConfiguration':'menuConfiguration:Entity1AssociatedMenuConfiguration',
                'entity1IntersectAttribute':'string:Entity1IntersectAttribute',
                'entity1LogicalName':'string:Entity1LogicalName',
                'entity2AssociatedMenuConfiguration':'menuConfiguration:Entity2AssociatedMenuConfiguration',
                'entity2IntersectAttribute':'string:Entity2IntersectAttribute',
                'entity2LogicalName':'string:Entity2LogicalName',
                'intersectEntityName':'string:IntersectEntityName'
            };
        }
    });

    //endregion ManyToManyRelationshipMetadata

    //region MenuConfiguration

    function MenuConfiguration() {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, MenuConfiguration, {
        getMap: function () {
            return {
                'behavior':'string:Behavior',
                'group':'string:Group',
                'label':'localizedLabelSet:Label',
                'order':'int:Order'
            };
        }
    });

    //endregion MenuConfiguration

    //region OneToManyRelationshipMetadata

    function OneToManyRelationshipMetadata () {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, OneToManyRelationshipMetadata, {
        getMap: function () {
            return {
                'metadataId':'string:MetadataId',
                'hasChanged':'string:HasChanged',
                'isCustomRelationship':'boolean:IsCustomRelationship',
                'isCustomizable':'managedProperty:IsCustomizable',
                'isManaged':'boolean:IsManaged',
                'isValidForAdvancedFind':'boolean:IsValidForAdvancedFind',
                'schemaName':'string:SchemaName',
                'securityTypes':'string:SecurityTypes',
                'introducedVersion':'string:IntroducedVersion',
                'relationshipType':'string:RelationshipType',
                'associatedMenuConfiguration':'menuConfiguration:AssociatedMenuConfiguration',
                'cascadeConfiguration':'cascadeConfiguration:CascadeConfiguration',
                'isHierarchical':'boolean:IsHierarchical',
                'referencedAttribute':'string:ReferencedAttribute',
                'referencedEntity':'string:ReferencedEntity',
                'referencingAttribute':'string:ReferencingAttribute',
                'referencingEntity':'string:ReferencingEntity'
            };
        }
    });

    //endregion OneToManyRelationshipMetadata

    //region CascadeConfiguration

    function CascadeConfiguration () {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, CascadeConfiguration, {
        getMap: function () {
            return {
                'assign':'string:Assign',
                'delete':'string:Delete',
                'merge':'string:Merge',
                'reparent':'string:Reparent',
                'share':'string:Share',
                'unshare':'string:Unshare'
            };
        }
    });

    //endregion CascadeConfiguration

    //region RolePrivilege

    function RolePrivilege () {
        COSA.MappableNode.call(this);
    }

    COSA.Util.deriveOverride(COSA.MappableNode, RolePrivilege, {
        getMap: function () {
            return {
                'businessUnitId': 'string:BusinessUnitId',
                'depth':'string:Depth',
                'privilegeId':'string:PrivilegeId'
            };
        }
    });

    //endregion RolePrivilege

    exports.LocalizedLabelSet = LocalizedLabelSet;
    exports.LocalizedLabel = LocalizedLabel;
    exports.ManagedProperty = ManagedProperty;
    exports.ValueNode = ValueNode;
    exports.BoolOptionSetMetadata = BoolOptionSetMetadata;
    exports.OptionSetMetadata = OptionSetMetadata;
    exports.OptionMetadata = OptionMetadata;
    exports.EntityMetadata = EntityMetadata;
    exports.SecurityPrivilegeMetadata = SecurityPrivilegeMetadata;
    exports.MenuConfiguration = MenuConfiguration;
    exports.ManyToManyRelationshipMetadata = ManyToManyRelationshipMetadata;
    exports.OneToManyRelationshipMetadata = OneToManyRelationshipMetadata;
    exports.CascadeConfiguration = CascadeConfiguration;
    exports.RolePrivilege = RolePrivilege;

})(COSA);
